﻿using CommunityToolkit.Mvvm.Messaging;
using Daq.Services;
using Daq.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Win32;
using Microsoft.Xaml.Behaviors;
using ScottPlot;
using ScottPlot.AxisPanels;
using ScottPlot.Plottables;
using System;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Telerik.Windows.Controls;

namespace Daq.Views
{
    /// <summary>
    /// DataManager.xaml 的交互逻辑
    /// </summary>
    public partial class DataManagerView : UserControl, IRecipient<TrendDataUpdatedMessage>
    {
        private readonly DataManagerViewModel dataManager;
        public DataManagerView()
        {
            InitializeComponent();
            
            dataManager = App.Current.Services.GetService<DataManagerViewModel>();
            if(dataManager == null)
            {
                throw new Exception();
            }
            DataContext = dataManager;
            hSpan = trendPlot.Plot.Add.HorizontalSpan(0, 0);
            InitTrendPlot();
            InitRawDataPlot();
            //WeakReferenceMessenger.Default.Register<TrendDataUpdatedMessage>(this, (obj, msg) => { Receive(msg); });
            dataManager.PropertyChanged += DataManager_PropertyChanged;
        }

        private void DataManager_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            //if (e.PropertyName is nameof(_viewModel.XData) or nameof(_viewModel.YData))
            //{
            //    // 直接使用 ViewModel 的数组引用（无复制）
            //    // 注意：SignalPlot 要求 X 轴均匀间隔，若 X 非均匀，可用 ScatterPlot 并开启降采样
            //    _signalPlot.Update(_viewModel.YData, sampleRate: 100); // sampleRate 为 X 轴间隔倒数

            //    // 启用降采样（当数据点 > 屏幕像素时自动简化）
            //    _signalPlot.Downsample = true;
            //    _signalPlot.DownsampleThreshold = (int)WpfPlotControl.ActualWidth * 2; // 屏幕宽度的2倍

            //    WpfPlotControl.Refresh();
            //}
            if (e.PropertyName == nameof(dataManager.TrendDataList))
            {
                UpdateTrendData(dataManager.TrendDataList);
            }
            else if(e.PropertyName == nameof(dataManager.RawData))
            {
                UpdateRawData(dataManager.RawData);
            }
        }

        private void UpdateRawData(double[]? rawData)
        {
            rawDataPlot.Plot.PlottableList.Clear();
            if (rawData == null) return;
            rawDataSignal = rawDataPlot.Plot.Add.Signal(rawData);
            rawDataSignal.LineWidth = 1;
            rawDataPlot.Plot.Axes.AutoScale();
            rawDataPlot.Refresh();
        }

        private void UpdateTrendData(double[]? data)
        {
            if (trendSignal != null)
            {
                trendPlot.Plot.PlottableList.Remove(trendSignal);
            }
            if (data != null)
            {
                trendSignal = trendPlot.Plot.Add.Signal(data);
                trendSignal.Color = new Color(244, 119, 180);
                //ScottPlot.AxisRules.MaximumBoundary rule = new(
                //    xAxis: trendPlot.Plot.Axes.Bottom,
                //    yAxis: trendPlot.Plot.Axes.Left,
                //    limits: AxisLimits.HorizontalOnly(0, data.Length));

                //trendPlot.Plot.Axes.Rules.Clear();
                //trendPlot.Plot.Axes.Rules.Add(rule);
            }
            hSpan.Left = 0;
            hSpan.Right = 0;
            trendPlot.Plot.Axes.AutoScale();
            trendPlot.Refresh();
            return;
        }

        private HorizontalSpan hSpan; 
        private AxisSpanUnderMouse? SpanBeingDragged = null;
        private Signal? trendSignal;
        private Signal? triggerCountSignal;
        private Signal? rawDataSignal;
        private LeftAxis? triggerCountAxis;
        private DateTime dataStartTime = DateTime.Now;
        private async void btnExportReport_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            //string extension = "xlsx";
            //SaveFileDialog dialog = new Microsoft.Win32.SaveFileDialog()
            //{
            //    DefaultExt = extension,
            //    Filter = string.Format("{1} files (.{0})|.{0}|All files (.)|.", extension, "Excel"),
            //    FilterIndex = 1
            //};
            //if (dialog.ShowDialog() == true)
            //{
            //    try
            //    {
            //        Stream stream = dialog.OpenFile();
            //        gridviewData.ExportAsync(stream,
            //        new GridViewExportOptions()
            //        {
            //            Format = ExportFormat.ExcelML,
            //            ShowColumnFooters = true,
            //            ShowColumnHeaders = true,
            //            ShowGroupFooters = true
            //        }, true);
            //        gridviewData.ElementExportedToDocument += gridviewData_ElementExportedToDocument;
            //        //RadWindow.Alert(new DialogParameters { Header = "导出数据", Content = "数据导出成功。" });
            //    }
            //    catch(Exception ex)
            //    {
            //        MessageBox.Show("导出失败：" + ex.Message);
            //    }
            //}
        }

        private void gridviewData_ElementExportedToDocument(object sender, GridViewElementExportedToDocumentEventArgs e)
        {
            Debug.WriteLine("导出完成");
        }

        private void gridviewData_ElementExportingToDocument(object sender, GridViewElementExportingToDocumentEventArgs e)
        {
            Debug.WriteLine("开始导出");
        }

        private void InitRawDataPlot()
        {
            rawDataPlot.UserInputProcessor.DoubleLeftClickBenchmark(false);
        }
        private void InitTrendPlot()
        {
            // Disable the benchmark display toggle action
            trendPlot.UserInputProcessor.DoubleLeftClickBenchmark(false);

            trendPlot.MouseDown += FormsPlot1_MouseDown;
            trendPlot.MouseUp += FormsPlot1_MouseUp;
            trendPlot.MouseMove += FormsPlot1_MouseMove;
            trendPlot.MouseLeave += (s, e) => { Cursor = Cursors.Arrow; };

            hSpan.LineStyle.Width = 2f;
            //hSpan.LineStyle.Pattern = LinePattern.Dashed;
            hSpan.IsDraggable = true;
            hSpan.IsResizable = true;
            ScottPlot.TickGenerators.NumericAutomatic tickGenX = new();
            tickGenX.MinimumTickSpacing = 200;
            trendPlot.Plot.Axes.Bottom.TickGenerator = tickGenX;
            trendPlot.Plot.ShowLegend();
            
            trendPlot.Plot.RenderManager.RenderStarting += (s, e) =>
            {
                Tick[] ticks = trendPlot.Plot.Axes.Bottom.TickGenerator.Ticks;
                for (int i = 0; i < ticks.Length; i++)
                {
                    //DateTime dt = DateTime.FromOADate(ticks[i].Position);
                    if (ticks[i].Position > TimeSpan.MaxValue.TotalMinutes) continue;
                    var timeSpan = TimeSpan.FromMinutes(ticks[i].Position);//dt - dataStartTime;
                                                                           //string label = $"{dt:MMM} '{dt:yy}";
                    string label;
                    if (true)
                    {
                        //StringBuilder sb = new();
                        //if (timeSpan.Days != 0)
                        //{
                        //    sb.Append(timeSpan.Days);
                        //    sb.Append("天");
                        //}
                        //sb.Append(timeSpan.Hours);
                        //sb.Append("时");
                        //sb.Append(timeSpan.Minutes);
                        //sb.Append("分");
                        //label = sb.ToString();
                        label = timeSpan < TimeSpan.Zero ? "" : $"{timeSpan.Days}d {timeSpan.Hours:D2}:{timeSpan.Minutes:D2}";
                    }
                    else
                    {
                        DateTime time = dataStartTime + TimeSpan.FromMinutes(ticks[i].Position);
                        //label = time.ToString("MM月dd日HH:mm");
                        label = CustomFormatter(time);
                    }

                    ticks[i] = new Tick(ticks[i].Position, label);
                }
                trendPlot.Plot.Font.Automatic();
            };
            trendPlot.Plot.Font.Automatic();
            //InitCrossHair();



            trendPlot.Refresh();
            UpdateSelectedDataRange();
        }
        static string CustomFormatter(DateTime dt)
        {
            bool isMidnight = dt is { Hour: 0, Minute: 0 };//, Second: 0 };
            return isMidnight
                ? DateOnly.FromDateTime(dt).ToString()
                : TimeOnly.FromDateTime(dt).ToString();
        }
        private AxisSpanUnderMouse? GetSpanUnderMouse(float x, float y)
        {
            CoordinateRect rect = trendPlot.Plot.GetCoordinateRect(x, y, radius: 10);

            foreach (AxisSpan span in trendPlot.Plot.GetPlottables<AxisSpan>().Reverse())
            {
                AxisSpanUnderMouse? spanUnderMouse = span.UnderMouse(rect);
                if (spanUnderMouse is not null)
                    return spanUnderMouse;
            }

            return null;
        }

        private void FormsPlot1_MouseDown(object? sender, MouseButtonEventArgs e)
        {
            var point = e.GetPosition(sender as UIElement);
            float x = (float)point.X;
            float y = (float)point.Y;
            var thingUnderMouse = GetSpanUnderMouse(x, y);
            if (thingUnderMouse is not null)
            {
                SpanBeingDragged = thingUnderMouse;
                trendPlot.UserInputProcessor.Disable(); // disable panning while dragging
            }
        }
        private void UpdateSelectedDataRange()
        {
            TimeSpan left = TimeSpan.FromMinutes(hSpan.Left);
            TimeSpan right = TimeSpan.FromMinutes(hSpan.Right);
            TimeSpan span = right - left + TimeSpan.FromMinutes(1);
            //WeakReferenceMessenger.Default.Send<SelectedDataRange, string>(new SelectedDataRange { Start = (int)hSpan.Left, End = (int)hSpan.Right }, "updateSelectedDataRange");
            dataManager.DatabaseStartTime = left;
            dataManager.DatabaseEndTime = right;
            hSpan.LegendText = $"时间段：{left.Days}天{left.Hours}时{left.Minutes}分 ~ {right.Days}天{right.Hours}时{right.Minutes}分\n共　计：{span.Days}天{span.Hours}时{span.Minutes}分";
        }
        private void FormsPlot1_MouseUp(object? sender, MouseButtonEventArgs e)
        {
            SpanBeingDragged = null;
            trendPlot.UserInputProcessor.Enable(); // enable panning
            if (hSpan != null)
            {
                //if (hSpan.Left < 0)
                //{
                //    hSpan.Left = 0;
                //}
                //if (hSpan.Right < 0)
                //{
                //    hSpan.Right = 0;
                //}
                UpdateSelectedDataRange();
            }
            trendPlot.Refresh();
        }

        private void FormsPlot1_MouseMove(object? sender, MouseEventArgs e)
        {
            var point = e.GetPosition(sender as UIElement);
            float x = (float)point.X;
            float y = (float)point.Y;
            if (SpanBeingDragged is not null)
            {
                //if (x < 0) x = 0;
                // currently dragging something so update it
                Coordinates mouseNow = trendPlot.Plot.GetCoordinates(x, y);
                if (mouseNow.X < 0) mouseNow.X = 0;
                SpanBeingDragged.DragTo(mouseNow);
                if (hSpan.Left < 0)
                {
                    hSpan.Left = 0;
                }
                trendPlot.Refresh();
            }
            else
            {
                // not dragging anything so just set the cursor based on what's under the mouse
                var spanUnderMouse = GetSpanUnderMouse(x, y);
                if (spanUnderMouse is null) Cursor = Cursors.Arrow;
                else if (spanUnderMouse.IsResizingHorizontally) Cursor = Cursors.SizeWE;
                else if (spanUnderMouse.IsResizingVertically) Cursor = Cursors.SizeNS;
                else if (spanUnderMouse.IsMoving) Cursor = Cursors.SizeAll;
            }
        }

        private void Receive(TrendDataUpdatedMessage msg)
        {
            //var vm = App.Current.Services.GetService<DataManagerViewModel>();
            //if (vm == null || vm.TrendData.Values == null || vm.TrendData.TriggerCounts == null)
            //{
            //    return;
            //}
            //if (trendSignal != null)
            //{
            //    trendPlot.Plot.PlottableList.Remove(trendSignal);
            //}
            //if (triggerCountSignal != null)
            //{
            //    trendPlot.Plot.PlottableList.Remove(triggerCountSignal);
            //}

            //double[] dataY = vm.TrendData.Values.ToArray();
            //double[] triggerCounts = vm.TrendData.TriggerCounts.ToArray();
            //triggerCountSignal = trendPlot.Plot.Add.Signal(triggerCounts);
            //triggerCountSignal.Color = new Color(244, 119, 180);

            ////double[] dataX = new double[dataY.Length];
            ////for (int i = 0; i < dataY.Length; i++) 
            ////{
            ////    dataX[i] = i * 60;
            ////}
            //dataStartTime = vm.TrendData.StartTime;
            //trendSignal = trendPlot.Plot.Add.Signal(dataY);
            //trendSignal.Color = new Color(31, 119, 180);
            //trendSignal.MinRenderIndex = 0;
            ////signal.Data.XOffset = 0;// dataStartTime.ToOADate();
            //hSpan.Right = dataY.Length / 2;
            //hSpan.Left = dataY.Length / 2;
            //UpdateSelectedDataRange();
            ////signal.Data.Period = 1.0;
            ////trendPlot.Plot.Axes.DateTimeTicksBottom();
            ////trendPlot.Plot.RenderManager.RenderStarting += (s, e) =>
            ////{
            ////    Tick[] ticks = trendPlot.Plot.Axes.Bottom.TickGenerator.Ticks;
            ////    for (int i = 0; i < ticks.Length; i++)
            ////    {
            ////        DateTime dt = DateTime.FromOADate(ticks[i].Position);
            ////        var timeSpan = TimeSpan.FromMinutes(ticks[i].Position);//dt - dataStartTime;
            ////        //string label = $"{dt:MMM} '{dt:yy}";
            ////        StringBuilder sb = new();
            ////        if (timeSpan.Days != 0)
            ////        {
            ////            sb.Append(timeSpan.Days);
            ////            sb.Append("天");
            ////        }
            ////        sb.Append(timeSpan.Hours);
            ////        sb.Append("时");
            ////        sb.Append(timeSpan.Minutes);
            ////        sb.Append("分");
            ////        ticks[i] = new Tick(ticks[i].Position, sb.ToString());
            ////    }
            ////};


            //RefreshTriggerCountAxis();


            //trendPlot.Plot.Axes.AutoScale();
            //trendPlot.Plot.Font.Automatic();
            //trendPlot.Refresh();

            //if (rawDataSignal != null)
            //{
            //    rawDataPlot.Plot.PlottableList.Remove(rawDataSignal);
            //}
            //rawDataPlot.Refresh();
        }

        private void RefreshTriggerCountAxis()
        {
            if (triggerCountAxis != null)
            {
                trendPlot.Plot.Axes.Remove(triggerCountAxis);
            }
            triggerCountAxis = trendPlot.Plot.Axes.AddLeftAxis();
            triggerCountAxis.LabelText = $"异常点";
            triggerCountAxis.LabelFontColor = Colors.Red;
            triggerCountAxis.Label.SetBestFont();
            triggerCountAxis.SizeWhenNoData = 1;
            triggerCountSignal.Axes.YAxis = triggerCountAxis;
        }

        void IRecipient<TrendDataUpdatedMessage>.Receive(TrendDataUpdatedMessage message)
        {
            Receive(message);
        }

        private void checkBoxLockX_Checked(object sender, RoutedEventArgs e)
        {
            AxisLimits limits = trendPlot.Plot.Axes.GetLimits();
            ScottPlot.AxisRules.LockedHorizontal rule = new(trendPlot.Plot.Axes.Bottom, limits.Left, limits.Right);
            trendPlot.Plot.Axes.Rules.Add(rule);
        }

        private void checkBoxLockX_Unchecked(object sender, RoutedEventArgs e)
        {
            for(int i = trendPlot.Plot.Axes.Rules.Count - 1; i >= 0; i--)
            {
                if (trendPlot.Plot.Axes.Rules[i] is ScottPlot.AxisRules.LockedHorizontal)
                {
                    trendPlot.Plot.Axes.Rules.RemoveAt(i);
                }
            }
        }

        private void checkBoxLockY_Checked(object sender, RoutedEventArgs e)
        {
            AxisLimits limits = trendPlot.Plot.Axes.GetLimits();
            ScottPlot.AxisRules.LockedVertical rule = new(trendPlot.Plot.Axes.Left, limits.Bottom, limits.Top);
            trendPlot.Plot.Axes.Rules.Add(rule);
        }

        private void checkBoxLockY_Unchecked(object sender, RoutedEventArgs e)
        {
            for (int i = trendPlot.Plot.Axes.Rules.Count - 1; i >= 0; i--)
            {
                if (trendPlot.Plot.Axes.Rules[i] is ScottPlot.AxisRules.LockedVertical)
                {
                    trendPlot.Plot.Axes.Rules.RemoveAt(i);
                }
            }
        }

        private void buttonAutoScale_Click(object sender, RoutedEventArgs e)
        {
            trendPlot.Plot.Axes.AutoScale();
            trendPlot.Refresh();
        }

        private void checkBoxRawDataLockX_Checked(object sender, RoutedEventArgs e)
        {
            AxisLimits limits = rawDataPlot.Plot.Axes.GetLimits();
            ScottPlot.AxisRules.LockedHorizontal rule = new(rawDataPlot.Plot.Axes.Bottom, limits.Left, limits.Right);
            rawDataPlot.Plot.Axes.Rules.Add(rule);
        }

        private void checkBoxRawDataLockX_Unchecked(object sender, RoutedEventArgs e)
        {
            for (int i = rawDataPlot.Plot.Axes.Rules.Count - 1; i >= 0; i--)
            {
                if (rawDataPlot.Plot.Axes.Rules[i] is ScottPlot.AxisRules.LockedHorizontal)
                {
                    rawDataPlot.Plot.Axes.Rules.RemoveAt(i);
                }
            }
        }

        private void checkBoxRawDataLockY_Checked(object sender, RoutedEventArgs e)
        {
            AxisLimits limits = rawDataPlot.Plot.Axes.GetLimits();
            ScottPlot.AxisRules.LockedVertical rule = new(rawDataPlot.Plot.Axes.Left, limits.Bottom, limits.Top);
            rawDataPlot.Plot.Axes.Rules.Add(rule);
        }

        private void checkBoxRawDataLockY_Unchecked(object sender, RoutedEventArgs e)
        {
            for (int i = rawDataPlot.Plot.Axes.Rules.Count - 1; i >= 0; i--)
            {
                if (rawDataPlot.Plot.Axes.Rules[i] is ScottPlot.AxisRules.LockedVertical)
                {
                    rawDataPlot.Plot.Axes.Rules.RemoveAt(i);
                }
            }
        }

        private void buttonRawDataAutoScale_Click(object sender, RoutedEventArgs e)
        {
            rawDataPlot.Plot.Axes.AutoScale();
            rawDataPlot.Refresh();
        }
        //private async void ButtonQueryWithCondition_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
        //{
        //    var vm = App.Current.Services.GetService<DataManagerViewModel>();
        //    if (vm == null || vm.TrendData.Values == null || vm.TrendData.TriggerCounts == null)
        //    {
        //        return;
        //    }

        //    if (ComboBoxTriggerType1.SelectedItem == null)
        //    {
        //        return;
        //    }
        //    bool value1Valid = double.TryParse(TextBoxTriggerValue1.Text, out double value1);
        //    if (!value1Valid)
        //    {
        //        return;
        //    }
        //    TriggerType type1;
        //    if (ComboBoxTriggerType1.SelectedItem is ComboBoxItem item && item.Content != null)
        //    {
        //        type1 = GetTriggerType(item.Content.ToString());
        //    }
        //    else
        //    {
        //        return;
        //    }

        //    Logic logic;
        //    if (ComboBoxLogic.SelectedItem is ComboBoxItem itemLogic && itemLogic.Content != null)
        //    {
        //        logic = GetLogicType(itemLogic.Content.ToString());
        //    }
        //    else
        //    {
        //        logic = Logic.None;
        //    }

        //    bool value2Valid = double.TryParse(TextBoxTriggerValue2.Text, out double value2);
        //    TriggerType type2;
        //    if (ComboBoxTriggerType2.SelectedItem is ComboBoxItem item2 && item2.Content != null)
        //    {
        //        type2 = GetTriggerType(item2.Content.ToString());
        //    }
        //    else
        //    {
        //        type2 = TriggerType.None;
        //    }
        //    if (!value2Valid || type2 == TriggerType.None)
        //    {
        //        logic = Logic.None;
        //    }

        //    TriggerInfo info = new()
        //    {
        //        Type1 = type1,
        //        Value1 = CalcTriggerValue(vm.CurrentMetaData, vm.SelectedChannelName, value1),
        //        Logic = logic,
        //        Type2 = type2,
        //        Value2 = CalcTriggerValue(vm.CurrentMetaData, vm.SelectedChannelName, value2)
        //    };

        //    Stopwatch sw = new();
        //    sw.Start();
        //    var counts = await vm.DataManager.GetTriggerCounts(vm.SelectedDataFileName, vm.SelectedChannelName, info);
        //    if (counts == null) return;
        //    sw.Stop();
        //    Debug.WriteLine($"后处理耗时：{sw.ElapsedMilliseconds}ms");
        //    if (triggerCountSignal != null)
        //    {
        //        trendPlot.Plot.PlottableList.Remove(triggerCountSignal);
        //    }
        //    triggerCountSignal = trendPlot.Plot.Add.Signal(counts);
        //    triggerCountSignal.Color = new Color(244, 119, 180);
        //    //triggerCountSignal.LineStyle.Pattern = LinePattern.Dotted;
        //    RefreshTriggerCountAxis();
        //    trendPlot.Refresh();
        //    Debug.WriteLine(string.Join(',', counts));
        //}
    }

    public class TrendDataUpdatedMessage
    {

    }
}
